package com.laker.autotest.common.reporters;

import com.laker.autotest.common.utils.TestNGUtil;
import org.testng.*;
import org.testng.xml.XmlSuite;

import java.io.File;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

/**
 * 极简版 HTML 邮件报告生成器，仅依赖 TestNG，适合邮件展示
 */
public class EasyHtmlEmailReporter implements IReporter {
    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Override
    public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDirectory) {
        try {
            String reportDir = TestNGUtil.getReportDir();
            File dir = new File(reportDir);
            if (!dir.exists()) dir.mkdirs();
            File reportFile = new File(dir, TestNGUtil.getReportFileName());
            try (PrintWriter writer = new PrintWriter(new OutputStreamWriter(Files.newOutputStream(reportFile.toPath()), StandardCharsets.UTF_8))) {
                writer.println("<html><head><meta charset='UTF-8'><title>自动化测试报告</title>");
                writer.println("<style>body{font-family:'PingFang SC','Microsoft YaHei',Arial,sans-serif;background:#f5f6fa;color:#222;margin:0;padding:0;}table{border-collapse:collapse;width:100%;margin-bottom:24px;background:#fff;}th,td{border:1px solid #e3e8ee;padding:10px 8px;font-size:15px;}th{background:#eaf1fb;color:#1976d2;font-weight:600;}td{background:#fff;}tr:nth-child(even) td{background:#f7fafd;}.passed{color:#388e3c;font-weight:bold;}.failed{color:#d32f2f;font-weight:bold;}.skipped{color:#bfa100;font-weight:bold;}.stacktrace{white-space:pre-wrap;font-family:'Fira Mono','Consolas','monospace';background:#f8fafc;color:#c62828;border-radius:6px;padding:10px;font-size:13px;overflow-x:auto;}</style></head><body>");
                writer.println("<h1 style='color:#1976d2;border-left:6px solid #1976d2;padding-left:14px;'>自动化测试报告</h1>");
                writer.println("<p>生成时间：" + DATE_FORMAT.format(new Date()) + "</p>");
                // 汇总统计
                int totalPassed = 0, totalFailed = 0, totalSkipped = 0, total = 0;
                for (ISuite suite : suites) {
                    for (ISuiteResult result : suite.getResults().values()) {
                        ITestContext ctx = result.getTestContext();
                        totalPassed += ctx.getPassedTests().size();
                        totalFailed += ctx.getFailedTests().size();
                        totalSkipped += ctx.getSkippedTests().size();
                    }
                }
                total = totalPassed + totalFailed + totalSkipped;
                writer.println("<table><tr><th>总用例数</th><th>通过</th><th>失败</th><th>跳过</th></tr>");
                writer.println("<tr><td>" + total + "</td><td class='passed'>" + totalPassed + "</td><td class='failed'>" + totalFailed + "</td><td class='skipped'>" + totalSkipped + "</td></tr></table>");
                // 详细用例
                writer.println("<table><tr><th>测试类.方法</th><th>状态</th><th>开始时间</th><th>耗时(ms)</th><th>异常信息</th></tr>");
                for (ISuite suite : suites) {
                    for (ISuiteResult result : suite.getResults().values()) {
                        ITestContext ctx = result.getTestContext();
                        List<ITestResult> allResults = new ArrayList<>();
                        allResults.addAll(ctx.getPassedTests().getAllResults());
                        allResults.addAll(ctx.getFailedTests().getAllResults());
                        allResults.addAll(ctx.getSkippedTests().getAllResults());
                        allResults.sort(Comparator.comparingLong(ITestResult::getStartMillis));
                        for (ITestResult res : allResults) {
                            String classMethod = res.getTestClass().getRealClass().getSimpleName() + "." + res.getMethod().getMethodName();
                            String status = getStatusText(res);
                            String statusClass = getStatusClass(res);
                            String startTime = DATE_FORMAT.format(new Date(res.getStartMillis()));
                            long duration = res.getEndMillis() - res.getStartMillis();
                            String exception = getExceptionMessage(res);
                            writer.print("<tr>");
                            writer.print("<td>" + classMethod + "</td>");
                            writer.print("<td class='" + statusClass + "'>" + status + "</td>");
                            writer.print("<td>" + startTime + "</td>");
                            writer.print("<td>" + duration + "</td>");
                            writer.print("<td>" + (exception == null ? "" : "<div class='stacktrace'>" + exception + "</div>") + "</td>");
                            writer.println("</tr>");
                        }
                    }
                }
                writer.println("</table></body></html>");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private String getStatusText(ITestResult result) {
        switch (result.getStatus()) {
            case ITestResult.SUCCESS:
                return "通过";
            case ITestResult.FAILURE:
                return "失败";
            case ITestResult.SKIP:
                return "跳过";
            default:
                return "未知";
        }
    }

    private String getStatusClass(ITestResult result) {
        switch (result.getStatus()) {
            case ITestResult.SUCCESS:
                return "passed";
            case ITestResult.FAILURE:
                return "failed";
            case ITestResult.SKIP:
                return "skipped";
            default:
                return "";
        }
    }

    private String getExceptionMessage(ITestResult result) {
        Throwable t = result.getThrowable();
        if (t != null) {
            StringWriter sw = new StringWriter();
            PrintWriter pw = new PrintWriter(sw);
            t.printStackTrace(pw);
            return sw.toString();
        }
        return null;
    }
}

